#pragma once

#include <string>
#include <memory>


class AbstractBlock {
public:
    AbstractBlock();
    AbstractBlock(unsigned int size);
    AbstractBlock(unsigned int size, unsigned char * data);
    virtual ~AbstractBlock();

    unsigned int size() const;
    unsigned char * data() const;

    virtual std::string toString() const;

protected:
    unsigned int _size;
    unsigned char * _data;
};

class Block : public AbstractBlock {
public:
    Block(unsigned int size = 4096);
    Block(unsigned int size, unsigned char * data);
    Block(unsigned char c, unsigned int capacity = 4096, unsigned int repeat = 1);
    Block(Block && other);
    Block(const Block & other);
    ~Block();

    Block& operator=(const Block & other);

    std::string toString() const override;

private:
    unsigned int checkedAlign(unsigned int size);
};


#include <vector>
#include <memory>
class Blocks {
public:
    using iterator = std::vector<Block>::iterator;

    Blocks(unsigned int blockSize = 4096);

    unsigned int blockSize() { return _blockSize; }
    unsigned int len() { return _blocks.size(); }
    unsigned long long numberOfBytes() { return len() * _blockSize; }

    bool append(Block & block);
    std::unique_ptr<Block> remove(unsigned int index);
    std::shared_ptr<Block> get(unsigned int index);
    void clear();

    iterator begin() { return _blocks.begin(); }
    iterator end() { return _blocks.end(); }

private:
    unsigned int _blockSize;
    std::vector<Block> _blocks;
};


